#include "design_mode_examples.h"
#include "ornament.h"
#include "singleton.h"

#include "debug_macro.h"


#include <iostream>
#include <fstream>
#include <string>

using namespace std;

namespace DesignMode{

	OptParse::OptParse(const char* config_file)
	{
		mPara_list_ = nullptr;
		nAllocatedPara_ = 0;
		nUsedParameter_ = 0;
		if (config_file != nullptr)
		{
			std::ifstream istrm(config_file, ios_base::in);
			if (istrm != nullptr)
			{
				std::string config_line;
				while(! istrm.eof()){
					std::getline(istrm, config_line, '\n');
					if (config_line.at(0) != '#')
					{
						char* tmp = new char[config_line.size()+1];
						tmp[config_line.size()] = '\0';
						memcpy(tmp, config_line.c_str(), sizeof(char)*config_line.size());
						TrimBlank(tmp);
						config_line.assign(tmp);
						std::string config_key, config_value;
						std::string::size_type equal_pos = config_line.find_first_of('=');
						if (equal_pos != std::string::npos)
						{
							config_key.assign(config_line.substr(0, equal_pos));
							config_value.assign(config_line.substr(equal_pos+1));
							Insert(config_key.c_str(), "", config_value.c_str());
						}
					}

				}
				

			}
			istrm.close();
		}
	}

	OptParse::~OptParse(){}

	void OptParse::TrimBlank(char* in_out_str)
	{
		if (in_out_str != nullptr)
		{
			char* next_ptr = in_out_str;
			std::string out_str;
			while(*next_ptr != '\0')
			{
				if (*next_ptr != ' ' && *next_ptr != '\t')
				{
					out_str.push_back(*next_ptr);
				}
				next_ptr++;
			}
			memcpy(in_out_str, out_str.c_str(), sizeof(char)*out_str.size());
			*(in_out_str+ out_str.size()) = '\0';
		}
	}

	Parameter* OptParse::Insert(const char* name, const char* annotation, const char* value)
	{
		Parameter* new_para = nullptr;
		if (name != nullptr && annotation != nullptr && value != nullptr)
		{
			new_para = new Parameter(name, annotation, value);
			nAllocatedPara_++;
			nUsedParameter_++;
			if (new_para)
			{
				if (mPara_list_ == nullptr)
				{
					mPara_list_ = new_para;
				}else{
					Parameter *this_para = mPara_list_, * next_para = mPara_list_->next;
					while(next_para != nullptr){
						this_para = next_para;
						next_para = this_para->next;
					}
					this_para->next = new_para;
				}
			}
			
		}
		return new_para;
	}

	bool OptParse::GetParameterValue(const char* name)
	{
		if (name != nullptr)
		{
			Parameter* this_para = mPara_list_, *next_para = mPara_list_->next;
			while(this_para != nullptr){
				if (strcmp(this_para->para_name_, name) == 0)
				{
					return true;
				}
				this_para = next_para;
				next_para = this_para->next;
			}
			
		}
		return false;
	}


	bool OptParse::Register(const char* name)
	{
		if (name != nullptr)
		{
			Parameter* this_para = mPara_list_, *next_para = mPara_list_->next;
			while(this_para != nullptr){
				next_para = this_para->next;
				if (strcmp(this_para->para_name_, name) == 0)
				{
					return true;
				}
				this_para = next_para;
			}
			Parameter* new_para = new Parameter(name, nullptr, nullptr);
			this_para = new_para;
			return true;
		}
		return false;
	}


	void OptParse::DestroyParameters()
	{
		Parameter* next_para = mPara_list_, * tail = 0;
		while(next_para){
			tail = next_para->next;
			delete next_para;
			next_para = tail;
		}
	}

	void OptParse::ReleaseOneParameter(const char* name)
	{
		if (name != nullptr)
		{
			Parameter* this_para = mPara_list_, *next_para = nullptr;
			if (this_para ==nullptr)
			{
				return;
			}else{
				if (strcmp(this_para->para_name_, name) == 0)
				{
					mPara_list_ = mPara_list_->next;
					delete this_para;
					return;
				}else{
					while(this_para != nullptr){
						next_para = this_para;
						next_para = next_para->next;
						if (strcmp(next_para->para_name_, name) == 0)
						{
							this_para->next = next_para->next;
							delete next_para;
							return;
						}
						this_para = this_para->next;
					}
				}
			}
		}

	}


	int PerformOrnamentMode()
	{

		std::cout << "ornament mode start...\n";

		ParaGraph p("A party? For me? Thanks !");
		std::cout << "original\n";
		std::cout << p.getHTML() << std::endl;
		std::cout << "bold to original\n";
		std::cout << BoldParaGraph(p).getHTML() << std::endl;

		//////////////////////////////////////////////////////////////////////////
		std::cout << "italic to bold to original\n";
		std::cout << ItalicParaGraph(BoldParaGraph(p)).getHTML() << std::endl;

		//////////////////////////////////////////////////////////////////////////
		std::cout << "bold to bold to original\n";
		std::cout << BoldParaGraph(BoldParaGraph(p)).getHTML() << std::endl;

		//system("pause");
		return 0;

	}
	int PerformAdapterMode()
	{
		std::cout << "Adapter mode start...\n";
		


		std::cout << "Adapter mode end...\n";

		return 0;
	}

	int PerformFactoryMode()
	{
		std::cout << "Factory mode start...\n";

		std::cout << "Factory mode end...\n";
		return 0;
	}

	int PerformProxyMode()
	{
		std::cout << "Proxy mode start...\n";
		bool result = false;
		Player test_player;
		result = DesignMode::informWinner(&test_player);
		if (result)
		{
			std::cout << "Proxy mode test end ...\n";
		}
		return 0;
	}



	int StaticSingletonModeTest()
	{
		StaticLogger::log("test message", StaticLogger::kLogLevelDebug);
		std::vector<std::string> items;
		items.push_back("item1");
		items.push_back("item2");

		StaticLogger::log(items, StaticLogger::kLogLevelError);

		StaticLogger::tearDown();
		return 0;

	}


	int TrueSingletonModeTest()
	{
		TrueLogger::Instance().log("test message", TrueLogger::kLogLevelDebug);
		std::vector<std::string> items;
		items.push_back("item1");
		items.push_back("item2");

		TrueLogger::Instance().log(items, TrueLogger::kLogLevelError);

		return 0;

	}


	int PerformSingletonMode(SingletonType in_type)
	{
		std::cout << "Singleton mode start...\n";
		
		
		SingletonType this_type = in_type;
		switch(this_type){
		case STATIC_SINGLETON:
			std::cout << "Static Singleton mode start...\n";
			StaticSingletonModeTest();
			std::cout << "Static Singleton mode end...\n";
			break;
		case TRUE_SINGLETON:
			std::cout << "True Singleton mode start...\n";
			TrueSingletonModeTest();
			std::cout << "True Singleton mode end...\n";
			break;
		default:
			std::cerr << "No others ...\n";
			break;
		}

		std::cout << "Singleton mode end...\n";
		return 0;
	}
	int DoModePerform(const DesignMode::ModeType& design_mode)
	{
		using namespace DesignMode;
		SingletonType singleton_type = STATIC_SINGLETON;
		int rest = 0;
		switch(design_mode){
		case Singleton:
			rest = PerformSingletonMode(singleton_type);
			break;
		case Adapter:
			PerformAdapterMode();
			break;
		case Proxy:
			PerformProxyMode();
			break;
		case Factory:
			PerformFactoryMode();
			break;
		case Ornament:
			PerformOrnamentMode();
			break;
		default:
			break;

		}

		return rest;
	}





}